/*
 * Copyright (c) 2009 Frederic Daoud
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package rayures.services.persistence.impl;

import rayures.services.persistence.Dao;
import java.util.*;
import javax.persistence.*;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository("dao")
@Transactional
public class DaoImpl implements Dao {
  @PersistenceContext
  private EntityManager entityManager;

  public <T> List<T> loadAll(Class<T> modelClass) {
    return entityManager
      .createQuery("select a from " + modelClass.getName() + " a")
      .getResultList();
  }

  public <T> T findById(Class<T> modelClass, Integer id) {
    return entityManager.find(modelClass, id);
  }

  public <T> T findSingleByField(Class<T> modelClass, String field,
    Object value)
  {
    String queryString = "select m from " + modelClass.getName()
      + " m where m." + field + " = ?";
    Query query = entityManager.createQuery(queryString);
    query.setParameter(1, value);

    try {
      return (T) query.getSingleResult();
    }
    catch (NoResultException exc) {
      return null;
    }
  }

  public <T> T findSingleByQuery(Class<T> modelClass,
    String queryString, Object... parameters)
  {
    Query query = entityManager.createQuery(queryString);

    for (int i = 0, t = parameters.length; i < t; i++) {
      query.setParameter(i + 1, parameters[i]);
    }
    try {
      return (T) query.getSingleResult();
    }
    catch (NoResultException exc) {
      return null;
    }
  }

  public <T> List<T> findListByField(Class<T> modelClass, String field,
    Object value)
  {
    String queryString = "select m from " + modelClass.getName()
      + " m where m." + field + " = ?";
    Query query = entityManager.createQuery(queryString);
    query.setParameter(1, value);

    try {
      return query.getResultList();
    }
    catch (NoResultException exc) {
      return Collections.emptyList();
    }
  }

  public <T> List<T> findListByQuery(Class<T> modelClass,
    String queryString, Object... parameters)
  {
    Query query = entityManager.createQuery(queryString);

    for (int i = 0, t = parameters.length; i < t; i++) {
      query.setParameter(i + 1, parameters[i]);
    }
    try {
      return query.getResultList();
    }
    catch (NoResultException exc) {
      return Collections.emptyList();
    }
  }

  public void save(final Object modelObject) {
    entityManager.persist(modelObject);
  }

  public void removeById(final Class<?> modelClass, Integer idValue) {
    entityManager.remove(findById(modelClass, idValue));
  }
}
